#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h> 
#include <stdarg.h>

#define PORT 10081
#define BUFFER_SIZE 4096
#define MAX_CLIENTS 50
#define MAX_SKIP_CLIENT 10
#define MAX_GAMES 10
#define DEVICE_ID_LEN 20
// 每付牌的个数
#define CARDS_PER_DECK 54
// 最大6付牌，同数值有4个，最多24
#define MAX_SAME_NUM 24
// 每个人最多持有的牌数
#define MAX_CARDS_PER_PLAYER 41
#define MAX_TIMEOUT 60

#define HEARTBEAT_PREFIX "HEARTBEAT:"
#define START_PREFIX "START:"
#define RELOAD_PREFIX "RELOAD:"
#define CONNECT_PREFIX "CONNECT:"
#define GAME_PREFIX "GAME:"
#define CARD_PREFIX "CARD:"
#define ACK_PREFIX "ACK:"
#define SYNC_PREFIX "SYNC:"
#define SKIP_PREFIX "SKIP:"
#define GIVEUP_PREFIX "GIVEUP:"

struct GameState;

// 客户端地址结构
struct Client {
    struct sockaddr_in addr;
    int active;
    time_t last_heartbeat;
    char device_id[DEVICE_ID_LEN];
    struct GameState* game;

    // 游戏相关信息
    int role; //0 表示空，1-8表示位置
    int cards[MAX_CARDS_PER_PLAYER]; //1表示黑桃3，2表示黑桃4..，53表示小王，54表示大王
    int card_count;
    int game_point; //比赛过程吃的分
    int game_result; //完赛排名
    int giveup; //为1表示主动认输
};

char card_output_msg[BUFFER_SIZE];
struct Client clients[MAX_CLIENTS];
int client_count = 0;
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
int sockfd;

// 游戏结构
struct GameState {
    int active;
    struct Client *clients[8];
    int skip_count;
    int skip_roles[MAX_SKIP_CLIENT];
    char room[DEVICE_ID_LEN];
    int game_type;
    int index;
    int step_count; 
    int need_auto_play;   

    int current_turn; //当前轮到谁
    int current_point; //当前的分数

    time_t last_time;
    int last_role; //最后一次出牌的人
    int last_card_value; //最后一次出的牌的值
    int last_card_count; //最后一次出的牌的张数
};

struct GameState game_states[MAX_GAMES] = {
    [0 ... MAX_GAMES - 1] = {
        .active = 0,
        .skip_count = 0,
        .need_auto_play = 0,
        .clients = {NULL},
        .game_type = 0,
        .current_turn = -1,
        .current_point = 0,
        .last_time = 0,
        .last_role = 0,
        .last_card_value = 0,
        .last_card_count = 0
    }
};
//////////////////// 公共函数和定义 /////////////////////
void play_card(int card_num, int card_value, struct Client* client);
void skip_play(struct Client* client);

// 记录日志
void log_message(const char* format, ...) {
    FILE* log_file = fopen("app.log", "a");
    if (log_file == NULL) {
        perror("open log fail");
        return;
    }
    
    // 获取当前时间
    time_t now;
    time(&now);
    struct tm* timeinfo = localtime(&now);
    char time_str[20];
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", timeinfo);
    
    // 打印时间和日志级别
    fprintf(log_file, "[%s] ", time_str);
    
    // 处理可变参数
    va_list args;
    va_start(args, format);
    vfprintf(log_file, format, args);
    va_end(args);
    
    // 添加换行符
    fprintf(log_file, "\n");
    
    // 关闭文件
    fclose(log_file);
}

char* get_room(char * device_id) {
    char* hashPos = strchr(device_id, '#');
    if (hashPos != NULL) {
        return hashPos + 1;
    }
    return NULL;    
}

// 转发数据到所有客户端 
void forward_data(char* buffer, int len, struct sockaddr_in* sender_addr, int sockfd, struct Client* client) {
    struct GameState* game = client->game;
    if (game != NULL) {
        // 在游戏里的转发给本游戏内的
        for (int i = 0; i < game->game_type; i++) {
            if (game->clients[i]->active &&
                (sender_addr == NULL ||
                    strcmp(game->clients[i]->device_id, client->device_id) != 0)) {

                if (sendto(sockfd, buffer, len, 0,
                    (struct sockaddr*)&(game->clients[i]->addr),
                    sizeof(struct sockaddr_in)) < 0) {
                    perror("sendto failed");
                }
            }
        }
    } else {
        // 不在游戏里的转给不在游戏的，且device_id后的room标签相同的
        char* room = get_room(client->device_id);
        
        for (int i = 0; i < MAX_CLIENTS; i++) {
            if ((clients[i].active == 0) || (clients[i].device_id[0] == 0) || (clients[i].active == 1 && clients[i].game != NULL)) {
                continue;
            }            
            if (strcmp(clients[i].device_id, client->device_id) == 0) {
                continue;
            }
            char * roomi = get_room(clients[i].device_id);                
            if ((room == NULL && roomi != NULL) || 
                (room != NULL && roomi == NULL) ||
                (room != NULL && roomi != NULL && strcmp(room, roomi) != 0)
                ) {
                continue;
            }
            
            if (sendto(sockfd, buffer, len, 0,
                (struct sockaddr*)&(clients[i].addr),
                sizeof(struct sockaddr_in)) < 0) {
                perror("sendto failed");
            }                      
        }    
    }
}

// 初始化并洗牌，牌编号从1开始
void init_and_shuffle(int* cards, int total_cards) {
    // 初始化牌，从1开始编号
    for (int i = 0; i < total_cards; i++) {
        cards[i] = i % 54 + 1;
    }

    // 随机洗牌
    srand(time(NULL));
    for (int i = total_cards - 1; i > 0; i--) {
        int j = rand() % (i + 1);
        // 交换牌
        int temp = cards[i];
        cards[i] = cards[j];
        cards[j] = temp;
    }
}

void init_cards(struct GameState* game, int player_count, int deck_count) {
    for (int i = 0; i < player_count; i++) {
        memset(game->clients[i]->cards, 0, MAX_CARDS_PER_PLAYER * sizeof(int));
    }

    int total_cards = deck_count * CARDS_PER_DECK;
    int cards_per_player = total_cards / player_count;
    int remainder = total_cards % player_count;

    int* cards = (int*)malloc(total_cards * sizeof(int));
    if (cards == NULL) {
        printf("malloc fail\n");
        return;
    }

    // 初始化并洗牌
    init_and_shuffle(cards, total_cards);

    // 标记哪些玩家会多获得1张牌，最多8个玩家
    int has_extra[8];
    memset(has_extra, 0, sizeof(has_extra));
    
    int selected = 0;
    while (selected < remainder) {
        int random_index = rand() % player_count;
        if (has_extra[random_index] == 0) {
            has_extra[random_index] = 1;
            selected++;
        }
    }

    // 均分牌给玩家
    int index = 0;
    for (int i = 0; i < cards_per_player; i++) {
        for (int j = 0; j < player_count; j++) {
            game->clients[j]->cards[i] = cards[index++];
        }
    }

    // 余牌分给幸运者
    for (int j = 0; j < player_count; j++) {
        if (has_extra[j] == 1) {
            game->clients[j]->cards[cards_per_player] = cards[index++];
            game->clients[j]->card_count = cards_per_player + 1;
        } else {
            game->clients[j]->card_count = cards_per_player;
        }
    }

    free(cards);
}

void print_cards(int* p) {
    for (int i = 0; i < 41; i++) {
        printf("%d ", p[i]);
    }
    printf("\n");
}

void generateMiddleMessage(char *buffer, struct GameState* game) {
    // {current_turn}:{step_count}:{last_role}:{last_card_num}:{last_card_value}:
    //      {current_point}:{device_id1,num1,point1,giveup1;device_id2,num2,point2,giveup2..}
    int pos = sprintf(buffer, "%d:%d:%d:%d:%d:%d:", 
        game->current_turn, 
        game->step_count,
        game->last_role,
        game->last_card_count,
        game->last_card_value,
        game->current_point);
    for (int i = 0; i < game->game_type; i++) {
        int remain = game->clients[i]->card_count;
        if (remain > 10) {
            remain = 10;
        }
        pos += sprintf(buffer + pos, "%s,%d,%d,%d,%d;", 
            game->clients[i]->device_id, 
            remain, 
            game->clients[i]->game_point,
            game->clients[i]->giveup,
            game->clients[i]->game_result);
    }
    buffer[pos - 1] = '\0';
}

void generateGameMessage(char *buffer, char *middle, struct Client* client) {
    char temp[BUFFER_SIZE];
    int pos = sprintf(temp, "%s", GAME_PREFIX);
    int count = 0;
    for (int i = 0; i < MAX_CARDS_PER_PLAYER; i++) {
        if (client->cards[i] == 0) {
            continue;
        }
        count++;
        pos += sprintf(temp + pos, "%d,", client->cards[i]);
    }
    temp[pos - 1] = '\0';
    
    // 拼接最终结果
    if (count > 0) {        
        sprintf(buffer, "%s:%s", temp, middle);
    } else {
        sprintf(buffer, "%s:%s", GAME_PREFIX, middle);
    }
    //log_message(buffer);
}

void send_role_msg(struct Client* client) {
    // GAME:{cards}:{current_turn}:{step_count}:{last_role}:{last_card_num}:{last_card_value}:
    //    {current_point}:{device_id1,num1,point1,giveup1,result1;device_id2,num2,point2,giveup2,result2..}
    if (client->game == NULL) {
        log_message("client's game is null");
        return;
    }
    
    struct GameState* game = client->game;
    char middle_msg[BUFFER_SIZE];
    generateMiddleMessage(middle_msg, game);
    char game_msg[BUFFER_SIZE];
    generateGameMessage(game_msg, middle_msg, client);
    sendto(sockfd, game_msg, strlen(game_msg), 0,
           (struct sockaddr *)&(client->addr), sizeof(struct sockaddr_in)); 
}

void send_connect_msg(struct Client* client) {
    // CONNECT:{client_count}
    int room_count = 0;
    char* room = get_room(client->device_id);
    for (int i = 0; i < MAX_CLIENTS; i++) {
        char * roomi = get_room(clients[i].device_id);                
        if ((room == NULL && roomi != NULL) || 
            (room != NULL && roomi == NULL) ||
            (room != NULL && roomi != NULL && strcmp(room, roomi) != 0)
            ) {
            continue;
        }
            
        if (clients[i].active && clients[i].game == NULL) {
            room_count++;
        }
    }

    char buffer[BUFFER_SIZE];
    sprintf(buffer, "%s%d", CONNECT_PREFIX, room_count);
    sendto(sockfd, buffer, strlen(buffer), 0,
           (struct sockaddr *)&(client->addr), sizeof(struct sockaddr_in)); 
}

void send_join_msg(struct Client* client) {
    // JOIN:{device_id}:{client_count}
    char init_msg[BUFFER_SIZE];

    sprintf(init_msg, "%s:%s:%d", "JOIN", client->device_id, client_count);
    log_message("player:%s (%d) join", client->device_id, client_count);
    forward_data(init_msg, strlen(init_msg), NULL, sockfd, client);
}

void reset_game(struct GameState* new_game, int game_type) {
    new_game->active = 1;
    new_game->skip_count = 0;
    new_game->game_type = game_type;
    new_game->step_count = 0;
    new_game->current_point = 0;
    new_game->last_time = time(NULL);
    new_game->last_role = 0;
    new_game->last_card_value = 0;
    new_game->last_card_count = 0;
    for (int i = 0; i < game_type; i++) {
        new_game->clients[i]->game_point = 0;
        new_game->clients[i]->game_result = 0;
        new_game->clients[i]->giveup = 0;
    }
    // 分牌
    if (game_type == 2) {
        init_cards(new_game, 2, 1);
    } else if (game_type == 4) {
        init_cards(new_game, 4, 3);
    } else if (game_type == 6) {
        init_cards(new_game, 6, 4);
    } else if (game_type == 8) {
        init_cards(new_game, 8, 6);
    } else {
        log_message("do not support %d players", game_type);
    }
}

void send_game_msg(struct GameState* new_game) {
    // GAME:{cards}:{current_turn}:{step_count}:{last_role}:{last_card_num}:{last_card_value}:
    //    {current_point}:{device_id1,num1,point1,giveup1,result1;device_id2,num2,point2,giveup2,result2..}
    char middle_msg[BUFFER_SIZE];
    generateMiddleMessage(middle_msg, new_game);
    // 给每个节点发牌的消息
    char game_msg[BUFFER_SIZE];
    for (int i = 0; i < new_game->game_type; i++) {
        generateGameMessage(game_msg, middle_msg, new_game->clients[i]);
        sendto(sockfd, game_msg, strlen(game_msg), 0,
               (struct sockaddr *)&(new_game->clients[i]->addr), sizeof(struct sockaddr_in));
    }
    
}

void add_free_client(int game_type, int *available_count, struct Client* available_clients[10]) {
    for (int i = 0; i < MAX_CLIENTS; i++) {
        if (clients[i].game == NULL) {
            int skip_client = 0;
            for (int j = 0; j < *available_count; j++) {
                if (available_clients[j] == &clients[i]) {
                    skip_client = 1;
                    break;
                }
            }
            if (skip_client == 1) {
                continue;
            }
        
            available_clients[*available_count] = &clients[i];
            *available_count += 1;
            if (*available_count >= game_type) {
                break;
            }
        }
    } 
}

void start_game(int game_type, struct Client* start_client) {
    struct GameState* new_game = NULL;
    if (start_client->game != NULL) {
        new_game = start_client->game;
    } else {
        for (int i = 0; i < MAX_GAMES; i++) {
            if (game_states[i].active == 0) {
                new_game = &game_states[i];
                break;
            }
        }
    }

    if (new_game == NULL) {
        return;
    }
    
    // 获取空闲玩家
    struct Client* available_clients[10];
    int available_count = 0;
    char* room = get_room(start_client->device_id);
    for (int i = 0; i < MAX_CLIENTS; i++) {
        // 填了room的选择room相同的，没填room的选择没填room的
        char* roomi = get_room(clients[i].device_id);
        if ((room == NULL && roomi != NULL) || 
            (room != NULL && roomi == NULL) ||
            (room != NULL && roomi != NULL && strcmp(room, roomi) != 0)
            ) {
            continue;
        }
        
        if (clients[i].active && clients[i].game == NULL) {
            available_clients[available_count++] = &clients[i];
            if (available_count >= game_type) {
                break;
            }
        }
    }

    if (new_game->active == 0) {        
        // 开启全新的游戏
        if (available_count < game_type) {
            // 人数不够，先找空闲的
            add_free_client(game_type, &available_count, available_clients);
        }
        if (available_count < game_type) {
            log_message("player not enough %d < %d", available_count, game_type);
            return;
        }

        if (room == NULL) {
            new_game->room[0] = 0;
        } else {
            strncpy(new_game->room, room, DEVICE_ID_LEN - 1);
        }
        log_message("start new game(%d) with %d player, room %s", new_game->index, game_type, new_game->room);
        
        // 准备client
        for (int i = 0; i < game_type; i++) {
            new_game->clients[i] = available_clients[i];
            available_clients[i]->game = new_game;
            available_clients[i]->role = i + 1; //从1开始
        }
        
        //初始化游戏
        reset_game(new_game, game_type);
        
        // 首局以1最多的人先发牌
        int max_three_count = 0;
        int curr_three_count = 0;
        int first_player = 1;
        for (int i = 0; i < new_game->game_type; i++) {
            curr_three_count = 0;
            for (int j = 0; j < MAX_CARDS_PER_PLAYER; j++) {
                int card_value = new_game->clients[i]->cards[j];
                if (card_value < 52 && card_value % 13 == 1) {
                    curr_three_count++;
                }
            }
            if (curr_three_count > max_three_count) {
                max_three_count = curr_three_count;
                first_player = i + 1;
            }
        }
        new_game->current_turn = first_player;
        
        send_game_msg(new_game);
    } else {
        if (new_game->current_turn < 10) {
            log_message("game(%d) not end", new_game->index);
            return;
        }
        
        // 检查是否要调整client
        if (game_type != new_game->game_type) {
            if (game_type > new_game->game_type + available_count) {
                // 人数不够，先找空闲的
                add_free_client(game_type, &available_count, available_clients);
            }

            
            if (game_type > new_game->game_type + available_count) {
                // 人数还是不够，不让调整
                game_type = new_game->game_type;
            }
            
            // 准备client
            if (game_type > new_game->game_type) {
                // 补充client
                for (int i = new_game->game_type; i < game_type; i++) {
                    int index = i - new_game->game_type;
                    new_game->clients[i] = available_clients[index];
                    available_clients[index]->game = new_game;
                    available_clients[index]->role = i + 1; //从1开始
                }
            } else {
                // 剔除client
                for (int i = game_type; i < new_game->game_type; i++) {
                    new_game->clients[i]->game = NULL;
                    send_connect_msg(new_game->clients[i]);
                }
            }            
        }
        
        //初始化游戏
        reset_game(new_game, game_type);
        new_game->current_turn = new_game->current_turn % 10;
        send_game_msg(new_game);
    }
}

int get_client_index(struct sockaddr_in* addr, char * device_id) {
    int index = -1;
    for (int i = 0; i < MAX_CLIENTS; i++) {
        if (memcmp(&clients[i].addr, addr, sizeof(struct sockaddr_in)) == 0) {
            index = i;
            break;
        }
    }
    if (index == -1 && device_id != NULL) {
        for (int i = 0; i < MAX_CLIENTS; i++) {
            if (strcmp(clients[i].device_id, device_id) == 0) {
                clients[i].addr = *addr;
                index = i;
                break;
            }
		}
    }

	return index;

}

// 添加客户端到列表
struct Client* find_client_with_update(struct sockaddr_in *addr, char * device_id) {
	int index = get_client_index(addr, device_id);
    if (index == -1 && device_id == NULL) {
        return NULL;
    }    
    //log_message("find client by addr %s -> %d", device_id, index);
    
	// 已存在客户端，更新信息
    if (index != -1) {
        int is_recover = 0;
        int is_change_name = 0;
        
        // 退出重连
        clients[index].last_heartbeat = time(NULL);
        if (clients[index].active == 0) {
            client_count++;
            clients[index].active = 1;
            is_recover = 1;
        }
        
        // 名称改变
        if (device_id != NULL && strcmp(clients[index].device_id, device_id) != 0) {
            strncpy(clients[index].device_id, device_id, DEVICE_ID_LEN - 1);
            clients[index].device_id[DEVICE_ID_LEN - 1] = '\0';
            is_change_name = 1;
        }        
       
         // 重新发送加入信息
        if (is_recover || is_change_name) {
            log_message("Recover client %s %s:%d (%d)", device_id,
                inet_ntoa(clients[index].addr.sin_addr),
                ntohs(clients[index].addr.sin_port), client_count);
            send_join_msg(&clients[index]);
            if (clients[index].game != NULL) {
                send_role_msg(&clients[index]);
            }
        }
        
        return &clients[index];
    }
    
    // 添加新客户端
    if (client_count >= MAX_CLIENTS) {
        log_message("max clients reached, rejected new connection.");
        return NULL;
    }
    
    int first_inactive = -1;
    for (int i = 0; i < MAX_CLIENTS; i++) {
        if (clients[i].active == 0 && clients[i].game == NULL) {
            first_inactive = i;
            break;
        }
    }
    if (first_inactive == -1) {
        log_message("inactive not found, rejected new connection.");
        return NULL;
    }
    
    // 没有game可以加入的纯新的客户端
    int i = first_inactive;
    client_count++;
    clients[i].last_heartbeat = time(NULL);
    clients[i].addr = *addr;
    clients[i].active = 1;
    clients[i].role = 0;
    clients[i].giveup = 0;
    clients[i].game_point = 0;
    clients[i].card_count = 0;
    clients[i].game_result = 0;
    clients[i].game = NULL;
    strncpy(clients[i].device_id, device_id, DEVICE_ID_LEN - 1);
    clients[i].device_id[DEVICE_ID_LEN - 1] = '\0';

    log_message("New client %s %s:%d (%d)", device_id,
        inet_ntoa(clients[i].addr.sin_addr),
        ntohs(clients[i].addr.sin_port), client_count);
    
    // 发送加入信息
    send_join_msg(&clients[i]); 

    return &clients[i];
}

int find_free_index(char * room, int * free_indexs, int free_count) {
    if (free_count == 0) {
        return -1;
    }

    for (int i = 0; i < free_count; i++) {
        char* roomi = get_room(clients[free_indexs[i]].device_id);
        if (room[0] == 0 && roomi == NULL) {
            return i;
        }        
        if (room[0] != 0 && roomi != NULL && strcmp(room, roomi) == 0) {
            return i;
        }
    }
    return -1;
}

int getMinNonZero(int a, int b, int c) {
    int min;
    int nonZeroCount = 0; 
    
    if (a != 0) {
        min = a; 
        nonZeroCount++;
    }
    
    if (b != 0) {
        if (nonZeroCount == 0) {
            min = b;
        } else if (b < min) {
            min = b;
        }
        nonZeroCount++;
    }
    
    if (c != 0) {
        if (nonZeroCount == 0) {
            min = c;
        } else if (c < min) {
            min = c;
        }
        nonZeroCount++;
    }
    
    return (nonZeroCount == 0) ? 0 : min;
}

int map_value_to_index(int i) {
    if (i == 53) {
        return 14;
    } else if (i == 54) {
        return 15;
    } else if (i % 13 == 0) {
        return 13;
    } else {
        return i % 13;
    }
}

int map_index_to_value(int i) {
    if (i == 14) {
        return 53;
    } else if (i == 15) {
        return 54;
    } else {
        return i;
    }
}

int get_min_card(struct GameState *game, struct Client * client, int *card_num,  int *card_value) {
    int client_card[16];
    memset(client_card, 0, sizeof(client_card));

    for (int i = 0; i < MAX_CARDS_PER_PLAYER; i++) {
        if (client->cards[i] == 0) {
            continue;
        }
        client_card[map_value_to_index(client->cards[i])]++;
    }
    
    if (game->last_role == 0) {
        int min1 = 0;
        int min2 = 0;
        int min3 = 0;
        for (int i = 1; i < 16; i++) {
            if (min1 == 0 && client_card[i] == 1) {
                min1 = i;
            }
            if (min2 == 0 && client_card[i] == 2) {
                min2 = i;
            }
            if (min3 == 0 && client_card[i] == 3) {
                min3 = i;
            }
        }
        int index = getMinNonZero(min1, min2, min3);
        if (index != 0) {
            *card_value = map_index_to_value(index);
            *card_num = client_card[index];
            return 0;
        } else {
            for (int i = 1; i < 16; i++) {
                if (client_card[i] != 0) {
                    *card_value = map_index_to_value(i);
                    *card_num = client_card[i];
                    return 0;
                }
            }
        }        
    } else {
        for (int i = 1; i < 16; i++) {
            if (client_card[i] == game->last_card_count 
                && i > map_value_to_index(game->last_card_value)) {
                *card_value = map_index_to_value(i);
                *card_num = client_card[i];
                return 0;
            }
        }
        for (int i = 1; i < 16; i++) {
            if (client_card[i] >= 4 &&  client_card[i] > game->last_card_count) {
                *card_value = map_index_to_value(i);
                *card_num = client_card[i];
                return 1;
            }
        }
    }
    
    return -1;
}

void auto_play_game(struct GameState *game) {
    if (game->current_turn > 10 || game->current_turn <= 0) {
        return;
    }
    struct Client *client = game->clients[game->current_turn - 1];
    if (client->active == 1) {
        return;
    }

    int card_num;
    int card_value;
    int card_result;
    if (game->last_role == 0) {
        //自己大
        card_result = get_min_card(game, client, &card_num, &card_value);
        if (card_result == 0) {
            log_message("auto_play game(%d)-role(%d) %d %d",
                game->index, client->role, card_num, card_value);
            play_card(card_num, card_value, client);
        }        
        return;
    } 
    if (client->role % 2 == game->last_role % 2) {
        // 同伴大
        log_message("auto_play game(%d)-role(%d) skip1",
            game->index, client->role);
        skip_play(client);
    } else {
        // 对方大
        card_result = get_min_card(game, client, &card_num, &card_value);
        if (card_result == 0) {
            log_message("auto_play game(%d)-role(%d) %d %d",
                game->index, client->role, card_num, card_value);
            play_card(card_num, card_value, client);
        } else if (card_result == 1) {
            if (game->current_point > 10 || game->last_card_count > 4) {
                log_message("auto_play game(%d)-role(%d) %d %d",
                    game->index, client->role, card_num, card_value);
                play_card(card_num, card_value, client);
            } else {
                log_message("auto_play game(%d)-role(%d) skip2",
                    game->index, client->role);
                skip_play(client);
            }            
        } else {
            log_message("auto_play game(%d)-role(%d) skip3",
                game->index, client->role);
            skip_play(client);
        }
    }    
}

// 心跳检查线程函数
void *heartbeat_check_thread() {
    int free_indexs[MAX_CLIENTS];
    int free_count = 0;
    int beat_count = 0;
    struct GameState *game;
    
    while (1) {
        sleep(5);  // 最小频率5秒
        time_t current_time = time(NULL);
        
        beat_count += 5;
        if (beat_count > 1800) {
            beat_count = 0;
        }
        
        pthread_mutex_lock(&clients_mutex);
        free_count = 0;
        // 10秒检查一次超时的client为下线状态
        if (beat_count % 10 == 0) {
            for (int i = 0; i < MAX_CLIENTS; i++) {
                if (!clients[i].active) {
                    continue;
                }

                // 计算距离最后一次心跳的时间差
                double elapsed = difftime(current_time, clients[i].last_heartbeat);

                if (elapsed > MAX_TIMEOUT) {  // 超时未收到心跳
                    log_message("Client %s:%d heartbeat lost",
                           inet_ntoa(clients[i].addr.sin_addr),
                           ntohs(clients[i].addr.sin_port));
                    clients[i].active = 0;
                    client_count--;
                } else {
                    // 事先收集可用的空闲的client，这里不区分room
                    if (clients[i].game == NULL) {
                        free_indexs[free_count++] = i;
                    }
                }
            }
        }
        
        // 300秒，出牌操作超时
        if (beat_count % 300 == 0) {
            // TODO
            
        }
        
        // 5秒为game替补client，要求room相同，只拷贝addr和device_id
        for (int j = 0; j < MAX_GAMES; j++) {
            if (game_states[j].active == 0) {
                continue;
            }
            game = &game_states[j];
            
            // 寻找替补client
            for (int i = 0; i < game->game_type; i++) {
                if (game->clients[i]->active == 0 && free_count > 0) {
                    // 从free_indexs找room相同的client
                    int k = find_free_index(game->room, free_indexs, free_count);
                    if (k != -1) {
                        int m = free_indexs[k];
                        log_message("replace (%s) room(%s)(%d)", clients[m].device_id, game->room, i);
                        // 拷贝addr和device_id
                        game->clients[i]->active = 1;
                        game->clients[i]->addr = clients[m].addr;
                        strncpy(game->clients[i]->device_id, 
                            clients[m].device_id, 
                            DEVICE_ID_LEN - 1);
                        game->clients[i]->device_id[DEVICE_ID_LEN - 1] = '\0';
                        // 清理
                        memset(&clients[m], 0, sizeof(struct Client));
                        clients[m].active = 0;
                        // 将free_indexs数组减一
                        free_indexs[k] = free_indexs[free_count - 1];
                        free_count--;
                        // 发送加入消息
                        log_message("Game(%d) assign client %s",j, game->clients[i]->device_id);
                        send_join_msg(game->clients[i]);
                        send_role_msg(game->clients[i]); 
                        
                    }
                }
            }
            
            // 确实没有替补client时，启动自动打牌
            int is_all_active = 1;
            for (int i = 0; i < game->game_type; i++) {
                if (game->clients[i]->active == 0) {
                    is_all_active = 0;
                    break;
                }
            }
            if (is_all_active) {
                game->need_auto_play = 0;
            } else {
                if (game->need_auto_play < 6) {
                    game->need_auto_play++;
                }                
            }
            if (game->need_auto_play >= 6) {
                auto_play_game(game);
            }
        }
        
        // 120秒检查game下线
        if (beat_count % 120 == 0) {
            for (int j = 0; j < MAX_GAMES; j++) {
                if (game_states[j].active == 0) {
                    continue;
                }
                //log_message("check game %d", j);
                game = &game_states[j];
                int inactive_count = 0;
                for (int i = 0; i < game->game_type; i++) {
                    if (game->clients[i]->active == 0) {
                        inactive_count++;
                    }
                }
                if (inactive_count == game->game_type) {
                    log_message("game %d close", j);
                    game_states[j].active = 0;
                    for (int i = 0; i < game->game_type; i++) {
                        game->clients[i]->game = NULL;
                    }
                }
            }
        }
      
        pthread_mutex_unlock(&clients_mutex);

    }
    return NULL;
}

// 获取当前手上牌的分数
int get_handcard_point(struct Client* client) {
    int point = 0;
    for (int j = 0; j < MAX_CARDS_PER_PLAYER; j++) {
        int card_value = client->cards[j];
        if (card_value == 0) {
            continue;
        }
        if (card_value >= 53) {
            continue;
        }
        card_value = card_value % 13;
        if (card_value == 3) {
            point += 5;
        }
        else if (card_value == 8 || card_value == 11) {
            point += 10;
        }
    }
    return point;
}

// 查看有没有比自己落后的对方
int has_behind_opponent(struct Client* client) {
    if (client->giveup == 1) {
        return 0;
    }
    if (client->game_result == 0) {
        return 0;
    }
    
    struct GameState* game = client->game;
    int has_behind = 0;
    int start = 0;
    if ((client->role - 1) % 2 == 0) {
        start = 1;
    }

    for (int i = start; i < game->game_type; i += 2) {
        if (game->clients[i]->giveup == 1) {
            has_behind = 1;
            break;
        }
        if (game->clients[i]->game_result == 0 || game->clients[i]->game_result > client->game_result) {
            has_behind = 1;
            break;
        }
    }
    return has_behind;
}

void count_result(struct GameState* game, int* t1_sum, int* t2_sum, int * t1_first, int * t2_first, int * t1_result, int * t2_result) {
    int t1_point = 0; //奇数组
	int t2_point = 0; //偶数组
    int min_t2_index = 0;
	int min_t2_result = 10;
    int min_t1_index = 0;
	int min_t1_result = 10;
    
    // 桌面的分数是当前打完牌的人的
    game->clients[game->current_turn - 1]->game_point += game->current_point;
    
	//为每个client计算分数
    for (int i = 0; i < game->game_type; i++) {
        int card_point = get_handcard_point(game->clients[i]);
        int has_behind = has_behind_opponent(game->clients[i]);
        log_message("%s(%d) point:%d handcard:%d result:%d behind:%d", 
            game->clients[i]->device_id, i + 1, 
            game->clients[i]->game_point,
            card_point,
            game->clients[i]->game_result,
            has_behind);
        
        if (has_behind) {
            // 正向给本组加分
            if (i % 2 == 0) {
                t2_point += (card_point + game->clients[i]->game_point);
                if (game->clients[i]->game_result < min_t2_result 
                    && game->clients[i]->game_result != 0) {
                    min_t2_result = game->clients[i]->game_result;
                    min_t2_index = i;
                }
            } else {
                t1_point += (card_point + game->clients[i]->game_point);
                if (game->clients[i]->game_result < min_t1_result
                    && game->clients[i]->game_result != 0) {
                    min_t1_result = game->clients[i]->game_result;
                    min_t1_index = i;
                }
            }
        } else {
            // 反向给对方加分
            if (i % 2 == 0) {
                t1_point += (card_point + game->clients[i]->game_point);
            } else {
                t2_point += (card_point + game->clients[i]->game_point);
            }
        }        
    }
    *t1_sum = t1_point;
    *t2_sum = t2_point;
    *t1_first = min_t1_index;
    *t1_result = min_t1_result;
    *t2_first = min_t2_index;
    *t2_result = min_t2_result;
}

int get_next_turn(struct GameState* game) {
    int next_turn = game->current_turn;
    for (int i = 0; i < game->game_type; i++) {
        next_turn = (next_turn % game->game_type) + 1;
        if (game->clients[next_turn - 1]->giveup == 0 &&
            game->clients[next_turn - 1]->card_count > 0) {
            return next_turn;
        }
    }
    log_message("do not have next player");
    return game->current_turn;
}

int get_available_count(struct GameState* game) {
    int count = 0;
    for (int i = 0; i < game->game_type; i++) {
        if (game->clients[i]->active == 1 &&
            game->clients[i]->giveup == 0 &&
            game->clients[i]->card_count > 0) {
            count++;
        }
    }
    return count;
}

int in_skip_list(struct GameState* game, int role) {
    for (int i = 0; i < game->skip_count; i++) {
        if (game->skip_roles[i] == role) {
            return 1;
        }
    }
    return 0;
}

void send_play_ack(struct Client* client) {
    //ACK:{current_turn}:{step_count}:{last_role}:{last_card_num}:{last_card_value}:{play_role}:{play_remain}:{current_point}
    struct GameState* game = client->game;
    char buffer[BUFFER_SIZE];
    int remain = client->card_count;
    if (remain > 10) {
        remain = 10;
    }
    sprintf(buffer, "%s%d:%d:%d:%d:%d:%d:%d:%d",
        ACK_PREFIX,
        game->current_turn,
        game->step_count,
        game->last_role,
        game->last_card_count,
        game->last_card_value,
        client->role,
        remain,
        game->current_point);
    forward_data(buffer, strlen(buffer), NULL, sockfd, client);
}

void send_sync(struct Client* client, int t1_sum, int t2_sum) {
    //SYNC:{current_turn}:{step_count}:{t1_sum,t2_sum}:{device_id1,num1,point1,giveup1,result1;device_id2,num2,point2,giveup2,result2..}
    struct GameState* game = client->game;
    char buffer[BUFFER_SIZE];
    int remain = 0;
    int pos = sprintf(buffer, "%s%d:%d:%d,%d:", SYNC_PREFIX, game->current_turn, game->step_count, t1_sum, t2_sum);
    
    for (int i = 0; i < game->game_type; i++) {
        remain = game->clients[i]->card_count;
        if (remain > 10) {
            remain = 10;
        }
        pos += sprintf(buffer + pos, "%s,%d,%d,%d,%d;", 
            game->clients[i]->device_id, 
            remain, 
            game->clients[i]->game_point,
            game->clients[i]->giveup,
            game->clients[i]->game_result);
    }
    buffer[pos - 1] = '\0';
    forward_data(buffer, strlen(buffer), NULL, sockfd, client);
}

void do_game_finish(struct Client* client) {
    int t1_sum;
    int t2_sum;
    int t1_index;
    int t2_index;
    int t1_result;
    int t2_result;
    
	struct GameState* game = client->game;
    count_result(game, &t1_sum, &t2_sum, &t1_index, &t2_index, &t1_result, &t2_result);
    
    if (t1_sum > t2_sum) {
        log_message("game finish with t1 win %d > %d", t1_sum, t2_sum);
        game->current_turn = 11 + t1_index;
    } else if (t2_sum > t1_sum) {
        log_message("game finish with t2 win %d > %d", t2_sum, t1_sum);
        game->current_turn = 21 + t2_index;
    } else {
        log_message("game finish with draw %d = %d", t1_sum, t2_sum);
        if (t1_result < t2_result) {
            game->current_turn = 31 + t1_index;
        } else {
            game->current_turn = 31 + t2_index;        
        }
	}
	send_sync(client, t1_sum, t2_sum);
}

int get_game_result(struct GameState* game) {
    int result = 0;
    for (int i = 0; i < game->game_type; i++) {
        if (game->clients[i]->game_result != 0) {
            result++;
        }
    }
    return result + 1;        
}

int is_game_end(struct GameState* game) {
    // 检查游戏是否结束
    int t1_finished_count = 0;
    int t2_finished_count = 0;
    for (int i = 0; i < game->game_type; i++) {
        if (game->clients[i]->card_count == 0 || game->clients[i]->giveup == 1) {
            if (i % 2 == 0) {
                t2_finished_count++;
            } else {
                t1_finished_count++;
            }
        }
    }
    if ((t1_finished_count == game->game_type /2 ) || 
        (t2_finished_count == game->game_type / 2)) {
        log_message("game over with %d %d player finished", t1_finished_count, t2_finished_count);
        return 1;
    }
    return 0;
}

void play_card(int card_num, int card_value, struct Client* client) {
	// 检查出牌是否合法
    struct GameState* game = client->game;
    int card_mod_value = card_value % 13;
    int found_count = 0;
    int found_index[MAX_SAME_NUM];

    for (int i = 0; i < MAX_CARDS_PER_PLAYER; i++) {
        if (client->cards[i] == 0) {
            continue;
        }
        if ((card_value < 53 && client->cards[i] < 53 && client->cards[i] % 13 == card_mod_value) ||
            (card_value >= 53 && client->cards[i] == card_value))
        {
            found_index[found_count++] = i;
            if (found_count == card_num) {
                break;
            }
        }
    }
    if (found_count < card_num) {
        log_message("not enough card %s %d:%d", client->device_id, card_num, card_value);
        return;
	}
    // 检查是否比last的牌大，1表示黑桃3，2表示黑桃4..，53表示小王，54表示大王
    if (game->last_role != 0) {
        // 3张牌
        if (game->last_card_count <= 3 && card_num <= 3 &&
            ((game->last_card_count != card_num) ||
                (game->last_card_count == card_num && game->last_card_value >= card_value))) {
			log_message("card not correct %s %d:%d <= %d:%d", 
                client->device_id, card_num, card_value, 
                game->last_card_count, game->last_card_value);
            return;
        }
        if (game->last_card_count > 3 &&
            ((game->last_card_count > card_num) ||
                (game->last_card_count == card_num && game->last_card_value >= card_value))) {
            log_message("card not big enough %s %d:%d <= %d:%d", 
                client->device_id, card_num, card_value, 
                game->last_card_count, game->last_card_value);
            return;
        }
	}

    // 记录出牌
    for (int i = 0; i < card_num; i++) {
        client->cards[found_index[i]] = 0;
    }
    client->card_count -= card_num;
	// 发送出牌确认
    game->last_role = client->role;
    game->last_card_value = card_value;
    game->last_card_count = card_num;
    if (card_value == 3) {
        game->current_point += (5 * card_num);
    } else if (card_value == 8 || card_value == 11) {
        game->current_point += (10 * card_num);
    }

    // 出完牌检查是否游戏结束
    if (client->card_count == 0) {
        client->game_result = get_game_result(game);
        log_message("player %s finished with rank %d", client->device_id, client->game_result);
        if (is_game_end(game) == 1) {
            // 游戏结束
            do_game_finish(client);
            return;
        }
    }
	// 未结束发送出牌确认
    game->skip_count = 1;
    game->skip_roles[0] = client->role;
    
    game->step_count++;
    game->last_time = time(NULL);
    game->current_turn = get_next_turn(game);
	send_play_ack(client);
}

void skip_play(struct Client* client) {
    struct GameState* game = client->game;
    game->skip_roles[game->skip_count++] = client->role;
    game->step_count++;
    game->last_time = time(NULL);
    game->current_turn = get_next_turn(game);
  
    if (in_skip_list(game, game->current_turn) == 1) {
        // 一轮结束，记录分数，清除last
        struct Client* win_client = game->clients[game->last_role - 1];
		win_client->game_point += game->current_point;
        // 清理本来牌面的分
        game->current_point = 0;
        game->last_role = 0;
        game->last_card_value = 0;
        game->last_card_count = 0;
        send_sync(client, 0, 0);
        return;
    }    
	send_play_ack(client);
}

void giveup_play(struct Client* client) {
    //GIVEUP:{device_id}:{play_role}
    struct GameState* game = client->game;
    if (game == NULL) {
        return;
    }
    
    client->giveup = 1;    

    // 计算是否结束
    if (is_game_end(game) == 1) {
        // 游戏结束
        do_game_finish(client);
        return;
    }
        
    // 发送弃权消息
    char buffer[BUFFER_SIZE];
    sprintf(buffer, "%s%s:%d",
        GIVEUP_PREFIX,
        client->device_id,
        client->role);
    forward_data(buffer, strlen(buffer), NULL, sockfd, client);
    
    // 计算是否要调整发牌权
    if (game->current_turn == client->role) {
        skip_play(client);
    }
}

//////////////////// 主函数 /////////////////////

int main() {
    struct sockaddr_in server_addr, client_addr;
    char buffer[BUFFER_SIZE];
    socklen_t client_len = sizeof(client_addr);
    
    memset(clients, 0, sizeof(clients));
    for (int i = 0; i < MAX_GAMES; i++) {
        game_states[i].index = i;
    }
    for (int i = 0; i < MAX_CLIENTS; i++) {
        sprintf(clients[i].device_id, "robot%d", i);
    }
    
    // 创建socket 
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 绑定地址 
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    log_message("Waiting for clients...");
    
    // 启动心跳检查线程
    pthread_t tid;
    if (pthread_create(&tid, NULL, heartbeat_check_thread, NULL) != 0) {
        perror("pthread_create failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }    
    
    while (1) {
        int len = recvfrom(sockfd, buffer, BUFFER_SIZE, 0,
                           (struct sockaddr *)&client_addr, &client_len);

        if (len < 0) {
            perror("recvfrom failed");
            continue;
        }
        buffer[len] = '\0';

        // 处理心跳
        if (strstr(buffer, HEARTBEAT_PREFIX) == buffer) {
            pthread_mutex_lock(&clients_mutex);
            char * device_id = buffer + strlen(HEARTBEAT_PREFIX);
            (void)find_client_with_update(&client_addr, device_id);
            pthread_mutex_unlock(&clients_mutex);
            continue;
        }
        // 处理开始游戏
        if (strstr(buffer, START_PREFIX) == buffer) {
            int game_type;
            char device_id[DEVICE_ID_LEN];
            if (sscanf(buffer, START_PREFIX "%d:%s", &game_type, device_id) == 2) {
                pthread_mutex_lock(&clients_mutex);
                struct Client* client = find_client_with_update(&client_addr, device_id);
                if (client != NULL) {
                    start_game(game_type, client);
                }
                pthread_mutex_unlock(&clients_mutex);
            }
			continue;
        }
        // 重新发送当前玩家的牌
        if (strstr(buffer, RELOAD_PREFIX) == buffer) {
            char* device_id = buffer + strlen(RELOAD_PREFIX);
            pthread_mutex_lock(&clients_mutex);
            struct Client* client = find_client_with_update(&client_addr, device_id);
            if (client != NULL && client->game != NULL) {
                send_role_msg(client);                    
            } else {
                send_connect_msg(client);
            }
            pthread_mutex_unlock(&clients_mutex);
            continue;
        }
        // 打牌
        if (strstr(buffer, CARD_PREFIX) == buffer) {
            int card_num = 0;
            int card_value = 0;
            char device_id[DEVICE_ID_LEN];
            if (sscanf(buffer, CARD_PREFIX "%d:%d:%s", &card_num, &card_value, device_id) == 3) {
                pthread_mutex_lock(&clients_mutex);
                struct Client* client = find_client_with_update(&client_addr, device_id);
                if (client != NULL && client->game != NULL) {
                    if (card_value > 0 && card_num > 0 && client->role == client->game->current_turn) {
                        log_message("play:%s(%d) %d*%d -- %d", device_id, client->role, card_num, card_value + 2, client->game->step_count);
                        play_card(card_num, card_value, client);
                    } else {
                        log_message("invalid play:%s %d*%d - %d %d", device_id, card_num, card_value + 2, client->role, client->game->current_turn);
                    }
                }
                pthread_mutex_unlock(&clients_mutex);
            }
			continue;
        }
        // 跳过
        if (strstr(buffer, SKIP_PREFIX) == buffer) {
            char* device_id = buffer + strlen(SKIP_PREFIX);
            pthread_mutex_lock(&clients_mutex);
            struct Client* client = find_client_with_update(&client_addr, device_id);
            if (client != NULL && client->game != NULL) {
                if (client->role == client->game->current_turn && client->game->last_role != 0) {
                    skip_play(client);
                } else {                    
                    log_message("invalid skip %s %d-%d", device_id, client->role, client->game->current_turn);
                }
            }
            pthread_mutex_unlock(&clients_mutex);
			continue;
        }
        // 放弃
        if (strstr(buffer, GIVEUP_PREFIX) == buffer) {
            char* device_id = buffer + strlen(GIVEUP_PREFIX);
            pthread_mutex_lock(&clients_mutex);
            struct Client* client = find_client_with_update(&client_addr, device_id);
            if (client != NULL && client->game != NULL) {
                giveup_play(client);
            }
            pthread_mutex_unlock(&clients_mutex);
			continue;
        }

        // 转发语音数据
        pthread_mutex_lock(&clients_mutex);
        struct Client* client = find_client_with_update(&client_addr, NULL);
        if (client != NULL) {
            forward_data(buffer, len, &client_addr, sockfd, client);
            if (len < 1000) {
                log_message("Received sound from client");
            }            
        }
        pthread_mutex_unlock(&clients_mutex);        
    }

    close(sockfd);
    return 0;
}


